#pragma once

class Graphic_Particle
{
public:
	/* Conventional Data */
	Vector2 mPosition;
	Vector2 mVelocity;

	float	mLife;
	float	mLifeDelta;

	float	mBearing;
	float	mAngularVelocity;
	/* Optional Data */
	Vector2 mScale;
	Vector2 mScaleDelta;

	COLOR	mColor;

	bool	mRespawn;

	Graphic_Particle()
		: mPosition(), mVelocity(), mBearing(0.0f),
		mLife(0.0f), mLifeDelta(0.0f), mRespawn(true), mAngularVelocity(0.0f),
		mScale(1, 1), mScaleDelta(0, 0), mColor(ARGB(255,255,255,255))
	{
	}
};

template<class Policy_Init, class Policy_Action>
class Graphic_ParticleSystem
{
protected:
	Policy_Init					m_policy_Init;
	Policy_Action				m_policy_Action;

	std::deque <Graphic_Particle>	mParticles;
	size_t							mActiveCount;
public:
	Graphic_ParticleSystem(size_t Amount) throw(): mActiveCount(0) 
	{
		mParticles.assign(Amount, Graphic_Particle());
	};
	virtual ~Graphic_ParticleSystem() throw() {};

	inline size_t	MaxCount() const throw() { return mParticles.size(); }
	inline size_t	ActiveCount() const throw() { return mActiveCount; }
	inline void		Clear() throw () { mActiveCount = 0; }
	
	inline std::deque <Graphic_Particle> * GetParticles() throw() { return &mParticles; }

	inline virtual void Emit(const size_t & Amount, const Vector2 & Point)
	{
		size_t nSpawnAmount = Amount;
		if(mActiveCount + nSpawnAmount > mParticles.size())
			nSpawnAmount = mParticles.size() - mActiveCount;
		if(nSpawnAmount < 1) return;
		mActiveCount += nSpawnAmount;
		for(size_t nCount = mActiveCount - nSpawnAmount; nCount < mActiveCount; ++nCount)
		{
			mParticles[nCount].mPosition = Point;
			m_policy_Init(mParticles[nCount]);
			mParticles[nCount].mRespawn = false;
		}
	}
	inline virtual void Update(const float & Interval) throw()
	{
		m_policy_Action.Begin(Interval);		// Set all Data

		for(size_t i = 0; i < mActiveCount; )
		{
			m_policy_Action(mParticles[i]);
			if(mParticles[i].mRespawn)
			{
				std::swap(mParticles[i], mParticles[mActiveCount - 1]); // Move Last Particle to this
				mActiveCount--;
			}
			else
				i++;
		}
	}
};